import { type } from "os";

// ! --------类型别名
type A = string;

type StatusCode = 200 | 301 | 400 | 500 | 502;

type PossibleDataTypes = string | number | (() => unknown);

const status: StatusCode = 502;

interface Event {
  (name: string): number
}

type Handler = (e: Event) => void;

const clickHandler: Handler = (e) => { };
const moveHandler: Handler = (e) => { };
const dragHandler: Handler = (e) => { };

//声明一个对象类型
type ObjType = {
  name: string;
  age: number;
}


// 类型别名还能作为工具类型。工具类同样基于类型别名，只是多了个泛型。

//一旦接受了泛型，我们就叫它工具类型：
type Factory<T> = T | number | string;
//从这个角度看，工具类型就像一个函数一样，泛型是入参，内部逻辑基于入参进行某些操作，再返回一个新的类型。比如在上面这个工具类型中，我们就简单接受了一个泛型，然后把它作为联合类型的一个成员，返回了这个联合类型。
const foo: Factory<boolean> = true
// 当然，我们一般不会直接使用工具类型来做类型标注，而是再度声明一个新的类型别名：
type FactoryWithBool = Factory<boolean>;
const foo1: FactoryWithBool = true;

//通常我们使用大写的 T / K / U / V / M / O ...这种形式。如果为了可读性考虑，我们也可以写成大驼峰形式（即在驼峰命名的基础上，首字母也大写）的名称，比如：
type Factory1<NewType> = NewType | number | string;

// 声明一个简单、有实际意义的工具类型：
type MaybeNull<T> = T | null;
//这个工具类型会接受一个类型，并返回一个包括 null 的联合类型。这样一来，在实际使用时就可以确保你处理了可能为空值的属性读取与方法调用：
function process(input: MaybeNull<{ handler: () => {} }>) {
  input?.handler?.()
}

//类似的还有 MaybePromise、MaybeArray。
type MaybeArray<T> = T | T[];
// 函数泛型我们会在后面了解~
function esureArray<T>(input: MaybeArray<T>): T[] {
  return Array.isArray(input) ? input : [input]
}

console.log('esureArray__', esureArray('string'));
console.log('esureArray__', esureArray(['1', 2]));